###爬取B站视频

#引入外部模块
import requests
import re
import json
import subprocess
import os

##需要获取的b站视频的地址
bilibili_video_url = "https://www.bilibili.com/video/BV1zS4y1j7KF/?spm_id_from=333.337.search-card.all.click&vd_source=1a464f6e111298caedd6983554fcf493"
##需要获取的b站视频的标题
bilibili_video_title = "80后野狼王的士高经典舞曲《NoLimit》，洗脑神曲嗨翻全场"

#getResponseha函数    发送请求
def getResponse(url):
    print("发送请求")
    headers = {
        "user-agent":"Mozilla / 5.0(Windows NT 10.0;Win64;x64) AppleWebKit / 537.36(KHTML, likeGecko) Chrome / 130.0.0.0Safari / 537.36",
        "referer":"https://search.bilibili.com/all?vt=23685179&keyword=gelwaygirl&from_source=webtop_search&spm_id_from=333.999&search_source=2",
        "cookie":"buvid3 = F767F804 - A81F - C834 - 0EA0 - 8ABE35BA9B9854083infoc;b_nut = 1731232454;_uuid = AAA1023BD - E32A - 315C - 3594 - 7210ECDBFF410778991infoc;CURRENT_FNVAL = 4048;buvid_fp = 1e652e0a0f5613d8d44b6b0a2bd63b55;buvid4 = B85119C7 - 9BD8 - 70FD - F777 - 0D45C97DD89A65839 - 024111009 - UE1tu % 2FLIgkFaPk % 2FvT1Dxww % 3D % 3D;rpdid = | (umlY~m | m | m0J'u~JukJkRY~; header_theme_version=CLOSE; enable_web_push=DISABLE; home_feed_column=5; browser_resolution=1536-703; SESSDATA=0d3b79cf%2C1747212792%2C48089%2Ab1CjDClxxImlFaEIp49XI4k3P5fLJsVyW1xHdRoHGpqZNsox-8v-5UyK2j-V1OOjCZ32gSVnQ0U2o2SkppMm1RTVd2azdjbUNrRS1Fdm9JN0N6Q1hLRnZlZFhibC1NRDVQaW9CUDJES3B1NF9FaFM4MC1WWTJHbnQ2anJLUHcxOUNHaUJzVF9LclFnIIEC; bili_jct=21e775e82d6b8644f8e152f672609268; DedeUserID=1960247133; DedeUserID__ckMd5=d152b1c1925bc4f3; hit-dyn-v2=1; b_lsid=D103E81012_19332C47C07; match_float_version=ENABLE; bmg_af_switch=1; bmg_src_def_domain=i2.hdslb.com; bili_ticket=eyJhbGciOiJIUzI1NiIsImtpZCI6InMwMyIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzE5ODI4NzAsImlhdCI6MTczMTcyMzYxMCwicGx0IjotMX0.NDM0IFT5fkAS_figIjOw_gSmDpLV4UCpuh64cqojGoI; bili_ticket_expires=1731982810; sid=64wlmec3; bp_t_offset_1960247133=1000234661319802880; CURRENT_QUALITY=80; _dd_s=logs=1&id=a9243799-01d7-4962-b7de-dd51dcf572ca&created=1731723557716&expire=1731724629553"
    }
    res = requests.get(url=url , headers=headers)
    return res

#getVideoInfo函数   获取视频信息（视频地址，音频地址，视频标题）
def getVideoInfo():
    #发送请求
    res = getResponse(url = bilibili_video_url)
    #网页源代码
    html = res.text
    #包含视频、音频url的信息
    info = re.findall('<script>window.__playinfo__=(.*?)</script>',html)[0]
    #转换为json
    json_data = json.loads(info)
    #视频标题
    title = re.findall(f'<h1 data-title="(.*?)" title="{bilibili_video_title}"' ,html)[0].replace(' ','')
    new_title = re.sub(r'[\/*?<>|]','',title)
    print(f"视频标题：{new_title}")
    #获取视频、音频的url
    audio_url = json_data['data']['dash']['audio'][0]['baseUrl']
    print(f"音频url：{audio_url}")
    video_url = json_data['data']['dash']['video'][0]['baseUrl']
    print(f"视频url：{video_url}")
    return audio_url, video_url,new_title

#save函数     获取并合并视频、音频内容
def save(audio_url, video_url,title):
    #指定文件夹名称
    video_dir = "video"
    #在当前文件夹下创建一个名为video的文件夹
    os.makedirs(video_dir, exist_ok=True)   #exist_ok=True 如果目录已经存在，不会引发错误
    #创建合成前的视频、音频路径和合成后的视频路径
    audio_file_path = os.path.join(video_dir, f"{title}.mp3")   #os.path.join() 将多个路径组件连接成一个完整的路径
    video_file_path = os.path.join(video_dir, f"{title}.mp4")
    output_file_path = os.path.join(video_dir, f"bilibili_{title}.mp4")
    #获取视频、音频内容
    print("获取音频内容")
    audio_content = getResponse(url=audio_url).content
    print("获取视频内容")
    video_content = getResponse(url=video_url).content
    #写入视频、音频内容
    print("写入音频内容")
    with open(audio_file_path, mode='wb') as a_file:
        a_file.write(audio_content)
    print("写入视频内容")
    with open(video_file_path, mode='wb') as v_file:
        v_file.write(video_content)
    #使用ffmpeg合并视频、音频文件
    print("合并视频音频文件")
    cmd = [
        "ffmpeg",
        "-i", video_file_path,
        "-i", audio_file_path,
        "-c:v", "copy",
        "-c:a", "aac",
        "-strict", "experimental",
        output_file_path
    ]
    res = subprocess.run(cmd, shell=True)
    if res.returncode != 0:
        print(res.stderr)
        return -1
    else:
        print("合并成功")
    #移除原视频和音频文件 只保留合成后的文件
    # print("移除原音频和视频文件")
    # os.remove(audio_file_path)
    # os.remove(video_file_path)

    return 0

##调用函数
audio_url, video_url,title = getVideoInfo()
save(audio_url,video_url,title)